package com.huilian.tool.ali.applet.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.huilian.tool.ali.applet.service.AliAppletService;
import com.huilian.tool.common.config.AppletAliConfig;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author: loong
 * @create: 2023-04-07 16:09
 **/
@Service
public class AliAppletServiceImpl implements AliAppletService {
    @Resource
    private AppletAliConfig appletAliConfig;


    public static final String ALIPAY_GATEWAY_URL = "https://openapi.alipay.com/gateway.do";

    @Override
    public JSONObject getUserInfoShare(String code) throws AlipayApiException {
        String accessToken = this.getSystemOauthToken(code);
        AlipayClient alipayClient = new DefaultAlipayClient(ALIPAY_GATEWAY_URL, appletAliConfig.getAppId(), appletAliConfig.getPrivateKey(), "json", "UTF-8", appletAliConfig.getPublicKey(), "RSA2");
        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();

        AlipayUserInfoShareResponse response = alipayClient.execute(request, accessToken);
        JSONObject jsonObject = new JSONObject();
        if (response.isSuccess()) {
            jsonObject.put("avatarUrl", response.getAvatar());
            jsonObject.put("name", response.getNickName());
        } else {
            jsonObject.put("error", "error");
        }
        return jsonObject;
    }

    @Override
    public Map<String, String> getPhoneNumber(String sign, String content) throws Exception {
        if (StringUtils.isEmpty(sign)) {
            throw new RuntimeException("sign不能为空");
        }
        if (StringUtils.isEmpty(content)) {
            throw new RuntimeException("content不能为空");
        }

        String signType = "RSA2";
        String charset = "UTF-8";
        String encryptType = "AES";

        //判断是否为加密内容
        boolean isDataEncrypted = !content.startsWith("{");
        boolean signCheckPass = false;
        // 2. 验签
        String signContent = content;
        String publicKey = appletAliConfig.getPublicKey();
        // 如果是加密的报文则需要在密文的前后添加双引号
        String decryptKey = appletAliConfig.getAesKey();
        if (isDataEncrypted) {
            signContent = "\"" + signContent + "\"";
        }
        try {
            signCheckPass = AlipaySignature.rsaCheck(signContent, sign, publicKey, charset, signType);
        } catch (AlipayApiException e) {
            // 验签异常, 日志
        }
        if (!signCheckPass) {
            // 验签不通过（异常或者报文被篡改），终止流程（不需要做解密）
            throw new Exception("验签失败");
        }

        // 3. 解密
        String plainData = null;
        if (isDataEncrypted) {
            try {
                plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
            } catch (AlipayApiException e) {
                e.printStackTrace();
                //解密异常, 记录日志
                throw new Exception("解密异常");
            }
        } else {
            plainData = content;
        }

        Map<String, String> map = JSON.parseObject(plainData, new TypeReference<Map<String, String>>() {
        });
        return map;
    }

    @Override
    public Map<String, String> getPhoneNumber(String sign, String content, String publicKey, String decryptKey) throws Exception {
        if (StringUtils.isEmpty(sign)) {
            throw new RuntimeException("sign不能为空");
        }
        if (StringUtils.isEmpty(content)) {
            throw new RuntimeException("content不能为空");
        }

        String signType = "RSA2";
        String charset = "UTF-8";
        String encryptType = "AES";

        //判断是否为加密内容
        boolean isDataEncrypted = !content.startsWith("{");
        boolean signCheckPass = false;
        // 2. 验签
        String signContent = content;
        if (isDataEncrypted) {
            signContent = "\"" + signContent + "\"";
        }
        try {
            signCheckPass = AlipaySignature.rsaCheck(signContent, sign, publicKey, charset, signType);
        } catch (AlipayApiException e) {
            // 验签异常, 日志
        }
        if (!signCheckPass) {
            // 验签不通过（异常或者报文被篡改），终止流程（不需要做解密）
            throw new Exception("验签失败");
        }

        // 3. 解密
        String plainData = null;
        if (isDataEncrypted) {
            try {
                plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
            } catch (AlipayApiException e) {
                e.printStackTrace();
                //解密异常, 记录日志
                throw new Exception("解密异常");
            }
        } else {
            plainData = content;
        }

        Map<String, String> map = JSON.parseObject(plainData, new TypeReference<Map<String, String>>() {
        });
        return map;
    }

    @Override
    public String getSystemOauthToken(String code) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(ALIPAY_GATEWAY_URL, appletAliConfig.getAppId(), appletAliConfig.getPrivateKey(), "json", "UTF-8", appletAliConfig.getPublicKey(), "RSA2");
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(code);
        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
        return response.getAccessToken();
    }
}
